﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Gallio.Framework;
using MbUnit.Framework;
using MbUnit.Framework.ContractVerifiers;

namespace MyBuild.Tests.BuildInitiator
{
    [TestFixture]
    public class BuildInitiatorFixture
    {
        private ContinuousBuildServiceDetails details = new ContinuousBuildServiceDetails("", "*", "c:", "c:");
        [Test]
        public void Build_WhenSetUpIsNotYetCalled_CallingBuildWillThrowAnInvalidOpEx()
        {
            //Arrange
            //Act
            var bi = new BuildInitiatorFake();
            Assert.Throws<InvalidOperationException>(bi.Build);
            //Assert
        }

        [Test]
        public void Build_OnFirstCall_RunsBuildProcess()
        {
            //Arrange
            var wasInitiatedExternalProcessCalled = false;
            var bi = new BuildInitiatorFake();
            bi.InitiatedExternalProcessCalled += (s, e) => wasInitiatedExternalProcessCalled = true;
            bi.Setup(details, x => { });
            //Act
            bi.Build();
            //Assert
            Assert.IsTrue(wasInitiatedExternalProcessCalled);
        }
        [Test]
        public void Build_OnSecondCall_DoesNotRunBuildProcess()
        {
            //Arrange
            var wasInitiatedExternalProcessCalled = 0;
            var bi = new BuildInitiatorFake();
            bi.InitiatedExternalProcessCalled += (s, e) => wasInitiatedExternalProcessCalled++;
            bi.Setup(details, x => { });
            //Act
            bi.Build();
            bi.Build();
            //Assert
            Assert.AreEqual(1, wasInitiatedExternalProcessCalled);
        }

        [Test]
        public void Build_OnSecondCallWhenFirstCallHasFinished_RunsBuildProcessAgain()
        {
            //Arrange
            var wasInitiatedExternalProcessCalled = 0;
            var bi = new BuildInitiatorFake();
            bi.InitiatedExternalProcessCalled += (s, e) => wasInitiatedExternalProcessCalled++;
            bi.Setup(details, x => { });
            //Act
            bi.Build();
            bi.CallFinishBuild();
            bi.Build();
            //Assert
            Assert.AreEqual(2, wasInitiatedExternalProcessCalled);
        }
        [Test]
        public void Build_OnSecondCallWhenFirstCallHasNotFinished_FinishBulid_RunsBuildProcessAgain()
        {
            //Arrange
            var wasInitiatedExternalProcessCalled = 0;
            var bi = new BuildInitiatorFake();
            bi.InitiatedExternalProcessCalled += (s, e) => wasInitiatedExternalProcessCalled++;
            bi.Setup(details, x => { });
            //Act
            bi.Build();
            bi.Build();
            bi.CallFinishBuild();
            //Assert
            Assert.AreEqual(2, wasInitiatedExternalProcessCalled);
        }

        [Test]
        public void Build_ThreeBuildInvokationWithOneFinish_RunsBuildProcessTwice()
        {
            //Arrange
            var wasInitiatedExternalProcessCalled = 0;
            var bi = new BuildInitiatorFake();
            bi.InitiatedExternalProcessCalled += (s, e) => wasInitiatedExternalProcessCalled++;
            bi.Setup(details, x => { });
            //Act
            bi.Build();
            bi.Build();
            bi.Build();
            bi.CallFinishBuild();
            //Assert
            Assert.AreEqual(2, wasInitiatedExternalProcessCalled);
        }
    }

    class BuildInitiatorFake : MyBuild.BuildInitiator
    {
        public event EventHandler InitiatedExternalProcessCalled;

        protected override void InitiatedExternalProcess(FileInfo executeableFileInfo)
        {
            InitiatedExternalProcessCalled(this, EventArgs.Empty);
        }
        public void CallFinishBuild()
        {
            FinishedBuild();
        }
    }
}
